using System;
using System.Collections.Generic;
using System.Text;

using MyAI.NeuralNetworkLib.Specification;

namespace MyAI.NeuralNetworkLib.Implementation
{
    public class SimpleLayer : INeuralLayer
    {
        #region Vars
        private NeuronTypes _nType;
        private ActivationFunctionTypes _afType;
        private List<INeuron> _neuroList;
        private List<double> _afPrms;
        #endregion

        #region Constructor
        public SimpleLayer()
        { 
        
        }
        #endregion

        #region INeuralLayer Members
        
        public void GenerateLayer(int inputVectorDimention, int neuronNumber, 
            NeuronTypes n_type, ActivationFunctionTypes af_type, List<double> afPrms)
        {
            _nType = n_type;
            _afType = af_type;
            _afPrms = afPrms;
            _neuroList = new List<INeuron>();
            for (int i = 0; i < neuronNumber; i++)
            {
                INeuron tmpNeuron = NeuronFactory.Instance.CreateNeuron(_nType);
                tmpNeuron.Reset(inputVectorDimention, ActivationFunctionFactory.Instance.CreateActivationFunction(_afType), _afPrms, 0);
                _neuroList.Add(tmpNeuron);
            }
        }

        public List<INeuron> GetNeurons()
        {
            return _neuroList;
        }

        public INeuron GetNeuron(int i)
        {
            return _neuroList[i];
        }

        public INeuralLayer CreateFilialLayer(int neuronNumber)
        {
            INeuralLayer nl = new SimpleLayer();
            nl.GenerateLayer(this._neuroList.Count, neuronNumber, this._nType,
                this._afType, _afPrms);
            return nl;
        }

        public List<double> CalculateOutput(List<double> inputVector)
        {
            List<double> output = new List<double>();
            foreach (INeuron n in _neuroList)
            {
                if (n.Weights.Count != inputVector.Count)
                {
                    throw new ArgumentException("inputVector in different then neurin input wights dimention");
                }
                output.Add(n.Activate(inputVector));
            }
            return output;
        }

        /// <summary>
        /// Warning, only for internal use
        /// </summary>
        public void AddNeuron(INeuron neuron)
        { 
            
        }

        #endregion
    }
}
